package com.lgc.javathread.threadWaitTest.waitNotify;

/**
 * 建立三个线程，A线程打印10次A，B线程打印10次B,C线程打印10次C，要求线程同时运行，交替打印10次ABC
 *
 * 这个问题用Object的wait()，notify()就可以很方便的解决
 */
public class MyThreadPrinter2 implements Runnable {
    private String name;
    private Object self;
    private Object next;

    private MyThreadPrinter2(String name,Object self,Object next){
        this.name = name;
        this.self=self;
        this.next=next;
    }

//    ***** wait()的作用是让当前线程进入等待状态，同时，wait()也会让当前线程释放它所持有的锁。
//    直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法”，当前线程被唤醒(进入“就绪状态”
//    ***** notify()唤醒在此对象锁上等待的单个线程。

    //wait就是说线程在获取对象锁后，主动释放对象锁，同时本线程休眠。
    // 直到有其它线程调用对象的notify()唤醒该线程，才能继续获取对象锁，并继续执行。

    //相应的notify()就是对对象锁的唤醒操作。
    // 但有一点需要注意的是notify()调用后，并不是马上就释放对象锁的，
    // 而是在相应的synchronized(){}语句块执行结束，自动释放锁后，
    // JVM会在wait()对象锁的线程中随机选取一线程，赋予其对象锁，唤醒线程，继续执行。

    //这样就提供了在线程间同步、唤醒的操作。

    @Override
    public void run() {
        System.out.println(name+"开始"+String.valueOf(System.currentTimeMillis()));
        int count =1;
        while (count<=10){
//            System.out.println(name+"新循环"+String.valueOf(System.currentTimeMillis()));
            synchronized(self){
                synchronized (next){
                    System.out.println(name+" "+String.valueOf(count));
                    count++;

                    next.notify();
//                    try {
//                        Thread.sleep(10);
//                        System.out.println(name+"：notify1");
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }
                }

                try {
                    self.wait();
//                    System.out.println(name+"活了"+String.valueOf(System.currentTimeMillis()));

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String args[]) throws InterruptedException {
        Object a=new Object();
        Object b=new Object();
        Object c=new Object();

        MyThreadPrinter2 pa=new MyThreadPrinter2("A",a,b);
        MyThreadPrinter2 pb=new MyThreadPrinter2("B",b,c);
        MyThreadPrinter2 pc=new MyThreadPrinter2("C",c,a);

        new Thread(pa).start();
        Thread.sleep(100);  //确保按顺序A、B、C执行
        new Thread(pb).start();
        Thread.sleep(100);
        new Thread(pc).start();
    }
}
